<?php
namespace app\manage\controller;
use think\Controller;
use think\Config;
use think\Db;
use think\Loader;
use think\Request;
use think\Log;
use think\Response;
use traits\model\SoftDelete;
use app\common\controller\ReturnCode;

class Base extends Controller
{
    use SoftDelete;
    protected $deleteTime = 'delete_time';
    protected  $uid;
    protected  $group_id;
    protected  $user_info;
    protected  $behavior;
    protected  $request;

    protected function _initialize()
    {
        Log::init(['type'=>'File','path'=>LOG_PATH,'level'=>['error']]); // 初始化日志， 错误级别level及以上，才记录

        if($this->request->action() != 'dlsq'){
            $this->checkLong(); // 判断是否持久登录
            $this->uid = session('uid');

            if (!$this->uid){
                $this->redirect("login/index");
            }

            $this->user_info = model('Admin')->getInfoByMap(['id'=>$this->uid]);


            $this->request = Request::instance();
            $this->behavior = $this->request->module() . '/' . $this->request->controller() . '/' . $this->request->action();

            $active = model('AuthRule')->getActive($this->behavior);


            $this->assign('active',$active);
            $this->assign('behavior',$this->behavior);


            // 面包屑
            $mbx = model('AuthRule')->getMbx($this->behavior);
            $this->assign('mbx',$mbx);


            $con = $this->request->controller();

            $aga = model('AuthGroupAccess')->where('uid',$this->uid)->find();
            $this->group_id = $aga['group_id'];
            $group_info = model('AuthGroup')->getInfoByMap(['id'=>$aga['group_id']]);

            // 菜单栏
            $menu = model('AuthRule')->getMenuAdmin($group_info['rules']);

//            dump(json_decode(json_encode($menu),true));die;

            $menu2=[];
            foreach ($menu as $v){
                if($v['status']==1){
                    $menu2[]=$v;
                }
            }
            $this->assign('menu',$menu2);
//            $this->assign('menu',$menu);



            $this->assign('user_info',$this->user_info);
            $this->assign('group_info',$group_info);

            //未读消息
            $msgNum=model('MsgNotice')->where('role_type',2)->where('a_id',$this->uid)->where('status',0)->count();
            $this->assign('msgNum',$msgNum);


            $msg_timeout_minute = Db::name('system_config')->field('status,extra')->where(['_key' => 'msg_timeout_minute'])->find();
            if(empty($msg_timeout_minute)||$msg_timeout_minute['status']==0){
                $msgDef=model('MsgNotice')->where('role_type',2)->where('a_id',$this->uid)->where('msg_type',3)->where('status',0)->find();
                $this->assign('msgDef',json_encode($msgDef,JSON_UNESCAPED_UNICODE));
                $msgYou=model('MsgNotice')->where('role_type',2)->where('a_id',$this->uid)->where('msg_type',2)->where('status',0)->find();
                $this->assign('msgYou',json_encode($msgYou,JSON_UNESCAPED_UNICODE));
            }else{
                $selectTime=time()-($msg_timeout_minute['extra']*60);
                $msgDef=model('MsgNotice')->where('role_type',2)->where('a_id',$this->uid)->where('msg_type',3)->where('status',0)->where('create_time','>=',$selectTime)->find();
                $this->assign('msgDef',json_encode($msgDef,JSON_UNESCAPED_UNICODE));
                $msgYou=model('MsgNotice')->where('role_type',2)->where('a_id',$this->uid)->where('msg_type',2)->where('status',0)->where('create_time','>=',$selectTime)->find();
                $this->assign('msgYou',json_encode($msgYou,JSON_UNESCAPED_UNICODE));
            }


            if($con == 'Login' || $con == 'Index' || $aga->group_id == 1){
                // 不验证权限...
            }else{

                $auth = new \auth\Auth();
                $au = $auth->check($this->behavior, $this->uid);


                if(request()->isAjax()){
                    if (!$this->uid){
                        Response::create(['code'=>1004,'msg'=>'请先登录'], 'json')->send();exit;
                    }else{
                        if (!$au){
                            Response::create(['code'=>1014,'msg'=>'您没有权限'], 'json')->send();exit;
                        }
                    }
                }else{

                    if (request()->isGet()) {
                        if (!$this->uid){
                            $this->redirect("login/index");
                        }else{

                            if (!$au) $this->redirect('Index/error1');
                        }
                    }else{
                        if (!$au) $this->error('您没有权限');
                    }

                }

            }
        }

    }

    /**
     * 判断是否持久登录
     */
    public function checkLong(){
        $is_long = model('AdminToken')->editToken('checkRemember');

        if($is_long === false){    // 只允许一个客户端登录
            session('uid',null);  // 删除判断登录的凭据
            cookie('think_auth',null);
        }else{
            session("phone",$is_long['phone']);
            session("uid",$is_long['id']);
        }
    }


    /**
     * 发送短信验证码
     * @param string $phone
     * @return boolean
     */
    public function sendSms($phone)
    {
        $code = mt_rand(1000,9999);
        $conf = '【xxxx】验证码：#CODE#';
        $msg = str_replace('#CODE#',$code,$conf);
        $result = sendSmsCode($phone, $msg, $code, $smsname='login_code');
        return $result;
    }

    /**
     * 获取返回码数组  有返回值
     * @param string $code
     * @param array $data
     * @param string $msg
     * @return array
     */
    static public function showReturnCodeData($code = '', $data = [], $msg = '')
    {
        $return_data = [
            'code' => '500',
            'msg' => '未定义消息',
            'data' => $code == 1001 ? $data : [],
        ];
        if (empty($code)) return $return_data;
        $return_data['code'] = $code;
        if(!empty($msg)){
            $return_data['msg'] = $msg;
        }else if (isset(ReturnCode::$return_code[$code]) ) {
            $return_data['msg'] = ReturnCode::$return_code[$code];
        }
        return $return_data;
    }

    /**
     * 获取返回码数组别名函数 无返回值
     * @param string $code
     * @param string $msg
     * @return array
     */
    static public function showReturnCode($code = '', $msg = '')
    {
        return self::showReturnCodeData($code,[],$msg);

    }

    /**
     * 获取返回码json别名函数 有返回值
     * @param string $code
     * @param string $msg
     * @return json
     */
    static public function showJsonReturnCodeData($code = '', $data = [], $msg = ''){
        Config::set(['default_return_type'    => 'json',]);
        return self::showReturnCodeData($code, $data, $msg);
    }

    /**
     * 获取返回码json别名函数 无返回值
     * @param string $code
     * @param string $msg
     * @return json
     */
    static public function showJsonReturnCode($code = '', $msg = ''){
        Config::set(['default_return_type'    => 'json',]);
        return self::showReturnCodeData($code, [], $msg);
    }

    /**
     * 记录系统日志
     * @param string $behavior
     * @param array $arr
     */
    public function RecordSystemLog($uid,$behavior,$description)
    {
        $data['uid'] = $uid;
        $data['ip'] = $this->request->ip();
        $data['behavior'] = $behavior;
        $data['description'] = $description;
        model('SystemLog')->writeSystemLog($data);  // 日志入库
    }

    /**
     * 数据库字段 网页字段转换
     * #Date:
     * @param $array 转化数组
     * @return 返回数据数组
     */
    protected function buildParam($array=[])
    {
        $data=[];
        if (is_array($array)&&!empty($array)){
            foreach( $array as $item=>$value ){
                $data[$item] = $this->request->param($value);
            }
        }
        return $data;
    }


    /**
     * 快速修改
     * @param $array
     * @param bool|false $validate_name
     * @param string $model_name
     * @return array 返回code码
     */
    protected function editData($parameter = false, $validate_name = false, $model_name = false, $save_data = [])
    {
        if (empty($save_data)) {
            if ($parameter != false && is_array($parameter)) {
                $data = $this->buildParam($parameter);
            } else {
                $data = $this->request->post();
            }
        } else {
            $data = $save_data;
        }
        if (!$data) return $this->showReturnCode(1002);
        if($this->request->action() != 'dlsq') {
            if (!$this->uid) return $this->showReturnCode(1004);
        }
        if ($validate_name != false) {
            $result = $this->validate($data, $validate_name);
            if (true !== $result) return $this->showReturnCode(1003,$result);
        }
        if (!$model_name) return $this->showReturnCode(1010);
        $model_edit = Loader::model($model_name);
        if (!$model_edit) return $this->showReturnCode(1010);
        return $model_edit->editData($data);
    }

    protected function doModelAction($param_data,$validate_name = false, $model_name = false,$action_name='editData'){

        if ($validate_name != false) {
            $result = $this->validate($param_data, $validate_name);
            if (true !== $result) return $this->showReturnCode(1003,  $result);
        }
        if (!$model_name) return $this->showReturnCode(1010);
        $model_edit = Loader::model($model_name);
        if (!$model_edit) return $this->showReturnCode(1010);
        return $model_edit->$action_name($param_data);
    }

    /**
     * 创建随机数
     * @param int $num  随机数位数
     * @return string
     */
    public function builderRand($num=8){
        return substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, $num);
    }


    /**
     * 软删除
     */
    public function delete()
    {
        if($this->request->isAjax()){
            $id = input('post.id');
            $model = $this->request->controller();
            $infoTemp = model($model)->getInfoByMap('','','',false);
            if(isset($infoTemp['parent_id'])){
                $infosCount = model($model)->countNum(['parent_id'=>$id],false); // 查询子分类数量
                if($infosCount > 0)  return $this->showReturnCode(1009,'该分类下有子分类,请批量删除');
            }
            $res = model($model)->destroy($id);
            if($res){
                $this->RecordSystemLog($this->uid,$this->behavior,'删除成功,操作ID: '.$id);
                return $this->showReturnCode(1001);
            }else{
                return $this->showReturnCode(1009,'删除失败');
            }
        }else{
            return $this->showReturnCode(1002);
        }
    }

    public function status()
    {
        if($this->request->isAjax()){
            $id = input('post.id');
            $model = $this->request->controller();
            $res = model($model)->save(['status'=>input('post.status')],['id'=>$id]);
            if($res){
                $this->RecordSystemLog($this->uid,$this->behavior,'状态操作成功,操作ID: '.$id);
                return $this->showReturnCode(1001);
            }else{
                return $this->showReturnCode(1009,'操作失败');
            }
        }else{
            return $this->showReturnCode(1002);
        }
    }


    /*排序逻辑*/
    public function listorder()
    {
        if($this->request->isAjax()){
            $id = input('id');
            $listorder = input('listorder');
            if(!is_numeric($id) || !is_numeric($listorder)){
                return $this->showReturnCode(1003);
            }
            //获取控制器
            $model = request()->controller();
            $res =  model($model)->save(['listorder'=>$listorder], ['id'=>$id]); //跟新排序
            if($res){
                return $this->showReturnCode(1001);
            }else{
                return $this->showReturnCode(1009,'排序失败');
            }
        }else{
            return $this->showReturnCode(1002);
        }
    }


    /** 批量删除*/
    public function bdel()
    {
        if($this->request->isAjax()){
            $data = input('post.');
            $model = model($this->request->controller());
            $chilrenIds = [];
            // 查找子分类id
            foreach($data['ids'] as $v){
                $chilrenIds = $this->getChilrenId($v);
            }
            // 合并id
            $totalIds = array_unique(array_merge($data['ids'], array_unique($chilrenIds)));
            $idStr = implode(",",$totalIds);
            $res = $model->destroy($totalIds); // 软删除
            if($res){
                $this->RecordSystemLog($this->uid,$this->behavior,'批量删除成功,操作ID: '.$idStr);
                return $this->showReturnCode(1001);
            }else{
                return $this->showReturnCode(1009,'批量删除失败');
            }
        }else{
            return $this->showReturnCode(1002);
        }


    }

    // 软删除时,查找子权限id
    public function getChilrenId($authRuleId){
        $authRuleRes = model($this->request->controller())->select();
        return $this->_getChilrenId($authRuleRes,$authRuleId);
    }

    public function _getChilrenId($authRuleRes,$authRuleId){
        static $arr = array();
        foreach ($authRuleRes as $k => $v) {
            if($v['parent_id']==$authRuleId){
                $arr[] = $v['id'];
                $this->_getChilrenId($authRuleRes,$v['id']);
            }
        }
        return $arr;
    }

    public function getChannelArray()
    {
        $list = model('Channel')->getListByMap();
        $channels = [];
        foreach ($list as $k=>$v){
            $channels[$v['id']] = $v['name'];
        }
        return $channels;
    }

    public function getAdminName($id)
    {
        $user_info = model('Admin')->getInfoByMap(['id'=>$id]);

        return $user_info['realname'];
    }

    public function getCityName($id)
    {
        $city = Db::name('city')->where(['id'=>$id])->find();
        return $city['name'];
    }

    /*
     * @function TokenBucket 令牌限速
     * @params string $Uid  用户ID
     * @params string  $BucketName 令牌名称
     * @params string  $Time 令牌发放时间间隔
     * @params string  $BucketLimit 令牌桶的大小
     * return booblean  ture|false 是否超过请求
     */
    function tokenBucket($Uid = '', $BucketName = '',$Time = '',$BucketLimit = ''){
        $key = $Uid.':'.$BucketName;
        $Redis = new \Predis\Client();
        $check = $Redis->exists($key);
        if ($check) {
            $Redis->incr($key);
            $count = $Redis->get($key);
            if ($count > $BucketLimit) {
                return false;
            }
        }else {
            $Redis->incr($key);
            //限制时间为60秒
            $Redis->expire($key,$Time);
        }
        return true;
    }
}